package handler

import (
	"bytes"
	"encoding/json"
	"net/http"
	"os"

	"vod-service/config" // 替换为实际项目路径

	"github.com/gin-gonic/gin"
	"github.com/volcengine/volc-sdk-golang/service/vod/models/business"
	"github.com/volcengine/volc-sdk-golang/service/vod/models/request"
	"github.com/volcengine/volc-sdk-golang/service/vod/upload/consts"
	"github.com/volcengine/volc-sdk-golang/service/vod/upload/functions"
	"github.com/volcengine/volc-sdk-golang/service/vod/upload/model"
)

// 媒体文件上传参数（文件路径方式）
type UploadMediaFileReq struct {
	SpaceName    string `json:"space_name" binding:"required" example:"your-space"`        // 空间名称
	FilePath     string `json:"file_path" binding:"required" example:"/path/to/video.mp4"` // 本地文件路径
	CallbackArgs string `json:"callback_args" example:"my-callback"`                       // 回调参数
	Title        string `json:"title" example:"测试视频"`                                      // 素材标题
	Tags         string `json:"tags" example:"test,vod"`                                   // 标签（逗号分隔）
	Description  string `json:"description" example:"测试用视频素材"`                             // 描述
}

// 1. 媒体文件上传（文件路径）
func UploadMediaFileHandler(c *gin.Context) {
	var req UploadMediaFileReq
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, config.Response{
			Code:    400,
			Message: "参数错误: " + err.Error(),
		})
		return
	}

	// 校验文件是否存在
	if _, err := os.Stat(req.FilePath); os.IsNotExist(err) {
		c.JSON(http.StatusBadRequest, config.Response{
			Code:    400,
			Message: "文件不存在: " + req.FilePath,
		})
		return
	}

	// 构建上传功能配置（截图、元数据、选项信息）
	snapShotFunc := functions.SnapshotFunc(business.VodUploadFunctionInput{SnapshotTime: 1.3})
	getMetaFunc := functions.GetMetaFunc()
	addOptionFunc := functions.AddOptionInfoFunc(business.VodUploadFunctionInput{
		Title:       req.Title,
		Tags:        req.Tags,
		Description: req.Description,
		Category:    consts.CategoryVideo,
		RecordType:  2,
		Format:      "mp4",
	})
	vodFunctions := []business.VodUploadFunction{addOptionFunc, getMetaFunc, snapShotFunc}
	fbts, _ := json.Marshal(vodFunctions)

	// 构建VOD上传请求
	uploadReq := &request.VodUploadMaterialRequest{
		SpaceName:        req.SpaceName,
		FilePath:         req.FilePath,
		CallbackArgs:     req.CallbackArgs,
		Functions:        string(fbts),
		FileType:         consts.FileTypeMedia,
		FileExtension:    ".mp4",
		UploadHostPrefer: "",
	}

	// 调用VOD SDK
	instance := config.GetVodInstance()
	resp, _, err := instance.UploadMaterialWithCallback(uploadReq)
	if err != nil {
		c.JSON(http.StatusInternalServerError, config.Response{
			Code:    500,
			Message: "上传失败: " + err.Error(),
		})
		return
	}

	c.JSON(http.StatusOK, config.Response{
		Code:    0,
		Message: "上传成功",
		Data: gin.H{
			"request_id": resp.GetResponseMetadata().GetRequestId(),
			"mid":        resp.GetResult().GetData().GetMid(),
			"size":       resp.GetResult().GetData().GetSourceInfo().GetSize(),
		},
	})
}

// 媒体流上传参数（流方式）
type UploadMediaStreamReq struct {
	SpaceName    string `form:"space_name" binding:"required" example:"your-space"` // 空间名称
	CallbackArgs string `form:"callback_args" example:"my-callback"`                // 回调参数
	Title        string `form:"title" example:"流上传测试视频"`                            // 标题
	Tags         string `form:"tags" example:"test,stream"`                         // 标签
	Description  string `form:"description" example:"流上传的测试视频"`                     // 描述
}

// 2. 媒体流上传（流式上传）
func UploadMediaStreamHandler(c *gin.Context) {
	var req UploadMediaStreamReq
	if err := c.ShouldBind(&req); err != nil { // 流上传通常用form-data，故用ShouldBind而非ShouldBindJSON
		c.JSON(http.StatusBadRequest, config.Response{
			Code:    400,
			Message: "参数错误: " + err.Error(),
		})
		return
	}

	// 获取上传的文件流
	file, err := c.FormFile("file")
	if err != nil {
		c.JSON(http.StatusBadRequest, config.Response{
			Code:    400,
			Message: "获取文件流失败: " + err.Error(),
		})
		return
	}

	// 打开文件流
	src, err := file.Open()
	if err != nil {
		c.JSON(http.StatusInternalServerError, config.Response{
			Code:    500,
			Message: "打开文件流失败: " + err.Error(),
		})
		return
	}
	defer src.Close()

	// 读取文件内容到字节流
	content, err := os.ReadFile(file.Filename)
	if err != nil {
		c.JSON(http.StatusInternalServerError, config.Response{
			Code:    500,
			Message: "读取文件内容失败: " + err.Error(),
		})
		return
	}

	// 构建上传功能配置
	snapShotFunc := functions.SnapshotFunc(business.VodUploadFunctionInput{SnapshotTime: 1.3})
	getMetaFunc := functions.GetMetaFunc()
	addOptionFunc := functions.AddOptionInfoFunc(business.VodUploadFunctionInput{
		Title:       req.Title,
		Tags:        req.Tags,
		Description: req.Description,
		Category:    consts.CategoryVideo,
		RecordType:  2,
		Format:      "mp4",
	})
	vodFunctions := []business.VodUploadFunction{addOptionFunc, getMetaFunc, snapShotFunc}
	fbts, _ := json.Marshal(vodFunctions)

	// 构建流上传请求
	streamReq := &model.VodStreamUploadRequest{
		SpaceName:        req.SpaceName,
		Content:          bytes.NewReader(content), // 文件字节流
		Size:             int64(len(content)),
		CallbackArgs:     req.CallbackArgs,
		Functions:        string(fbts),
		FileType:         consts.FileTypeMedia,
		FileName:         file.Filename,
		FileExtension:    ".mp4",
		UploadHostPrefer: "",
	}

	// 调用VOD SDK
	instance := config.GetVodInstance()
	resp, _, err := instance.UploadMaterialStreamWithCallback(streamReq)
	if err != nil {
		c.JSON(http.StatusInternalServerError, config.Response{
			Code:    500,
			Message: "流上传失败: " + err.Error(),
		})
		return
	}

	c.JSON(http.StatusOK, config.Response{
		Code:    0,
		Message: "流上传成功",
		Data: gin.H{
			"request_id": resp.GetResponseMetadata().GetRequestId(),
			"mid":        resp.GetResult().GetData().GetMid(),
			"size":       resp.GetResult().GetData().GetSourceInfo().GetSize(),
		},
	})
}

// 图片文件上传参数（文件路径方式）
type UploadImageFileReq struct {
	SpaceName    string `json:"space_name" binding:"required" example:"your-space"`      // 空间名称
	FilePath     string `json:"file_path" binding:"required" example:"/path/to/img.jpg"` // 本地文件路径
	CallbackArgs string `json:"callback_args" example:"img-callback"`                    // 回调参数
	Title        string `json:"title" example:"测试图片"`                                    // 标题
	Tags         string `json:"tags" example:"test,image"`                               // 标签
	Description  string `json:"description" example:"测试用图片素材"`                           // 描述
}

// 3. 图片文件上传（文件路径）
func UploadImageFileHandler(c *gin.Context) {
	var req UploadImageFileReq
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, config.Response{
			Code:    400,
			Message: "参数错误: " + err.Error(),
		})
		return
	}

	// 校验文件是否存在
	if _, err := os.Stat(req.FilePath); os.IsNotExist(err) {
		c.JSON(http.StatusBadRequest, config.Response{
			Code:    400,
			Message: "文件不存在: " + req.FilePath,
		})
		return
	}

	// 构建上传功能配置
	getMetaFunc := functions.GetMetaFunc()
	addOptionFunc := functions.AddOptionInfoFunc(business.VodUploadFunctionInput{
		Title:       req.Title,
		Tags:        req.Tags,
		Description: req.Description,
		Category:    consts.CategoryImage,
		RecordType:  2,
		Format:      "jpg",
	})
	vodFunctions := []business.VodUploadFunction{addOptionFunc, getMetaFunc}
	fbts, _ := json.Marshal(vodFunctions)

	// 构建上传请求
	uploadReq := &request.VodUploadMaterialRequest{
		SpaceName:        req.SpaceName,
		FilePath:         req.FilePath,
		CallbackArgs:     req.CallbackArgs,
		Functions:        string(fbts),
		FileType:         consts.FileTypeImage,
		FileExtension:    ".jpg",
		UploadHostPrefer: "",
	}

	// 调用VOD SDK
	instance := config.GetVodInstance()
	resp, _, err := instance.UploadMaterialWithCallback(uploadReq)
	if err != nil {
		c.JSON(http.StatusInternalServerError, config.Response{
			Code:    500,
			Message: "图片上传失败: " + err.Error(),
		})
		return
	}

	c.JSON(http.StatusOK, config.Response{
		Code:    0,
		Message: "图片上传成功",
		Data: gin.H{
			"request_id": resp.GetResponseMetadata().GetRequestId(),
			"mid":        resp.GetResult().GetData().GetMid(),
		},
	})
}

// 4. 图片流上传（流式上传）
func UploadImageStreamHandler(c *gin.Context) {
	// 类似媒体流上传，区别在于FileType和Category
	var req struct {
		SpaceName    string `form:"space_name" binding:"required"`
		CallbackArgs string `form:"callback_args"`
		Title        string `form:"title"`
		Tags         string `form:"tags"`
		Description  string `form:"description"`
	}
	if err := c.ShouldBind(&req); err != nil {
		c.JSON(http.StatusBadRequest, config.Response{Code: 400, Message: "参数错误: " + err.Error()})
		return
	}

	file, err := c.FormFile("file")
	if err != nil {
		c.JSON(http.StatusBadRequest, config.Response{Code: 400, Message: "获取文件失败: " + err.Error()})
		return
	}
	src, err := file.Open()
	if err != nil {
		c.JSON(http.StatusInternalServerError, config.Response{Code: 500, Message: "打开文件失败: " + err.Error()})
		return
	}
	defer src.Close()

	content, err := os.ReadFile(file.Filename)
	if err != nil {
		c.JSON(http.StatusInternalServerError, config.Response{Code: 500, Message: "读取文件失败: " + err.Error()})
		return
	}

	// 构建功能配置（图片无需截图）
	getMetaFunc := functions.GetMetaFunc()
	addOptionFunc := functions.AddOptionInfoFunc(business.VodUploadFunctionInput{
		Title:       req.Title,
		Tags:        req.Tags,
		Description: req.Description,
		Category:    consts.CategoryImage,
		RecordType:  2,
		Format:      "jpg",
	})
	vodFunctions := []business.VodUploadFunction{addOptionFunc, getMetaFunc}
	fbts, _ := json.Marshal(vodFunctions)

	streamReq := &model.VodStreamUploadRequest{
		SpaceName:        req.SpaceName,
		Content:          bytes.NewReader(content),
		Size:             int64(len(content)),
		CallbackArgs:     req.CallbackArgs,
		Functions:        string(fbts),
		FileType:         consts.FileTypeImage,
		FileName:         file.Filename,
		FileExtension:    ".jpg",
		UploadHostPrefer: "",
	}

	instance := config.GetVodInstance()
	resp, _, err := instance.UploadMaterialStreamWithCallback(streamReq)
	if err != nil {
		c.JSON(http.StatusInternalServerError, config.Response{Code: 500, Message: "图片流上传失败: " + err.Error()})
		return
	}

	c.JSON(http.StatusOK, config.Response{
		Code:    0,
		Message: "图片流上传成功",
		Data: gin.H{
			"request_id": resp.GetResponseMetadata().GetRequestId(),
			"mid":        resp.GetResult().GetData().GetMid(),
		},
	})
}

// 5. 对象文件上传（字幕等，文件路径）
func UploadObjectFileHandler(c *gin.Context) {
	var req struct {
		SpaceName    string `json:"space_name" binding:"required"`
		FilePath     string `json:"file_path" binding:"required"`
		CallbackArgs string `json:"callback_args"`
		Title        string `json:"title"`
		Tags         string `json:"tags"`
		Description  string `json:"description"`
	}
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, config.Response{Code: 400, Message: "参数错误: " + err.Error()})
		return
	}

	if _, err := os.Stat(req.FilePath); os.IsNotExist(err) {
		c.JSON(http.StatusBadRequest, config.Response{Code: 400, Message: "文件不存在: " + req.FilePath})
		return
	}

	// 构建功能配置（对象文件无需截图）
	getMetaFunc := functions.GetMetaFunc()
	addOptionFunc := functions.AddOptionInfoFunc(business.VodUploadFunctionInput{
		Title:       req.Title,
		Tags:        req.Tags,
		Description: req.Description,
		Category:    consts.CategorySubtitle, // 对象类型：字幕
		RecordType:  2,
		Format:      "vtt",
	})
	vodFunctions := []business.VodUploadFunction{addOptionFunc, getMetaFunc}
	fbts, _ := json.Marshal(vodFunctions)

	uploadReq := &request.VodUploadMaterialRequest{
		SpaceName:        req.SpaceName,
		FilePath:         req.FilePath,
		CallbackArgs:     req.CallbackArgs,
		Functions:        string(fbts),
		FileType:         consts.FileTypeObject,
		FileExtension:    ".vtt",
		UploadHostPrefer: "",
	}

	instance := config.GetVodInstance()
	resp, _, err := instance.UploadMaterialWithCallback(uploadReq)
	if err != nil {
		c.JSON(http.StatusInternalServerError, config.Response{Code: 500, Message: "对象文件上传失败: " + err.Error()})
		return
	}

	c.JSON(http.StatusOK, config.Response{
		Code:    0,
		Message: "对象文件上传成功",
		Data: gin.H{
			"request_id": resp.GetResponseMetadata().GetRequestId(),
			"mid":        resp.GetResult().GetData().GetMid(),
		},
	})
}

// 6. 对象流上传（字幕等，流式上传）
func UploadObjectStreamHandler(c *gin.Context) {
	var req struct {
		SpaceName    string `form:"space_name" binding:"required"`
		CallbackArgs string `form:"callback_args"`
		Title        string `form:"title"`
		Tags         string `form:"tags"`
		Description  string `form:"description"`
	}
	if err := c.ShouldBind(&req); err != nil {
		c.JSON(http.StatusBadRequest, config.Response{Code: 400, Message: "参数错误: " + err.Error()})
		return
	}

	file, err := c.FormFile("file")
	if err != nil {
		c.JSON(http.StatusBadRequest, config.Response{Code: 400, Message: "获取文件失败: " + err.Error()})
		return
	}
	src, err := file.Open()
	if err != nil {
		c.JSON(http.StatusInternalServerError, config.Response{Code: 500, Message: "打开文件失败: " + err.Error()})
		return
	}
	defer src.Close()

	content, err := os.ReadFile(file.Filename)
	if err != nil {
		c.JSON(http.StatusInternalServerError, config.Response{Code: 500, Message: "读取文件失败: " + err.Error()})
		return
	}

	// 构建功能配置
	getMetaFunc := functions.GetMetaFunc()
	addOptionFunc := functions.AddOptionInfoFunc(business.VodUploadFunctionInput{
		Title:       req.Title,
		Tags:        req.Tags,
		Description: req.Description,
		Category:    consts.CategorySubtitle,
		RecordType:  2,
		Format:      "vtt",
	})
	vodFunctions := []business.VodUploadFunction{addOptionFunc, getMetaFunc}
	fbts, _ := json.Marshal(vodFunctions)

	streamReq := &model.VodStreamUploadRequest{
		SpaceName:        req.SpaceName,
		Content:          bytes.NewReader(content),
		Size:             int64(len(content)),
		CallbackArgs:     req.CallbackArgs,
		Functions:        string(fbts),
		FileType:         consts.FileTypeObject,
		FileName:         file.Filename,
		FileExtension:    ".vtt",
		UploadHostPrefer: "",
	}

	instance := config.GetVodInstance()
	resp, _, err := instance.UploadMaterialStreamWithCallback(streamReq)
	if err != nil {
		c.JSON(http.StatusInternalServerError, config.Response{Code: 500, Message: "对象流上传失败: " + err.Error()})
		return
	}

	c.JSON(http.StatusOK, config.Response{
		Code:    0,
		Message: "对象流上传成功",
		Data: gin.H{
			"request_id": resp.GetResponseMetadata().GetRequestId(),
			"mid":        resp.GetResult().GetData().GetMid(),
		},
	})
}

func RegisterMaterialRoutes(r *gin.Engine) {
	// 注册素材上传相关路由
	uploadMaterialGroup := r.Group("/api/v1/upload/material")
	{
		// 媒体上传
		uploadMaterialGroup.POST("/media/file", UploadMediaFileHandler)     // 媒体文件（路径）
		uploadMaterialGroup.POST("/media/stream", UploadMediaStreamHandler) // 媒体流（form-data）

		// 图片上传
		uploadMaterialGroup.POST("/image/file", UploadImageFileHandler)     // 图片文件（路径）
		uploadMaterialGroup.POST("/image/stream", UploadImageStreamHandler) // 图片流（form-data）

		// 对象上传（字幕等）
		uploadMaterialGroup.POST("/object/file", UploadObjectFileHandler)     // 对象文件（路径）
		uploadMaterialGroup.POST("/object/stream", UploadObjectStreamHandler) // 对象流（form-data）
	}
}
